<?php
/**
 * Talents come from diligence, and knowledge is gained by accumulation.
 *
 * @author: 晋<657306123@qq.com>
 */

namespace app\common\logic;

use app\common\model\Category;
use app\common\model\Collect;
use app\common\model\GalleryItem;
use app\common\model\Post;
use app\common\validate\CollectValidate;
use app\site\Controller;
use think\exception\ValidateException;
use Xin\Support\Num;
use Xin\Thinkphp5\Hint\Facade\Hint;

/**
 * Class CollectLogic
 */
class CollectLogic extends Controller{

	/**
	 * 收藏
	 *
	 * @param int $type
	 * @param int $topicId
	 * @return array|bool
	 */
	public function collect($type, $topicId){
		$data = $this->resolveData($type, $topicId);
		$this->validate($data, CollectValidate::class);

		if($id = $this->isCollected($type, $topicId)){
			$this->safeCallback(function() use ($type, $id){
				if($type == Collect::VISIT_CATEGORY_TYPE){
					Collect::where('id', $id)->update([
						'create_time' => $this->request->time(),
					]);
				}
			});
		}else{
			if(!$this->insertData($data)){
				return false;
			}

			$this->safeCallback(function() use ($type, $topicId){
				if($type == Collect::VISIT_CATEGORY_TYPE){
					Category::where('id', $topicId)->setInc('view_count');
				}elseif($type == Collect::POST_TYPE){
					Post::where('id', $topicId)->setInc('collect_count');
				}
			});
		}

		return $data;
	}

	/**
	 * 收藏并返回Response实例
	 *
	 * @param int $topicId
	 * @param int $type
	 * @return \think\Response
	 */
	public function collectWithResponse($type, $topicId){
		if(!($data = $this->collect($type, $topicId))){
			return Hint::error("收藏失败！");
		}

		return Hint::success("已收藏！", "", $data);
	}

	/**
	 * 取消收藏
	 *
	 * @param int $type
	 * @param int $topicId
	 * @return \think\Response
	 * @throws \think\Exception
	 * @throws \think\exception\PDOException
	 */
	public function unCollectWithResponse($type, $topicId){
		$uid = $this->user->getUserId();

		$map = [
			'uid'      => $uid,
			'type'     => $type,
			'topic_id' => $topicId,
		];
		if(Collect::where($map)->delete() === false){
			return Hint::error("取消收藏失败！");
		}

		$this->safeCallback(function() use ($type, $topicId){
			if($type == Collect::VISIT_CATEGORY_TYPE){
				Category::where('id', $topicId)->setDec('view_count');
			}elseif($type == Collect::POST_TYPE){
				Post::where('id', $topicId)->setDec('collect_count');
			}
		});

		return Hint::success("已取消收藏！", "", $map);
	}

	/**
	 * 获取我的收藏
	 *
	 * @param int $type
	 * @return \think\Paginator
	 * @throws \think\exception\DbException
	 */
	public function lists($type){
		$appId = $this->xApp->getAppId();
		$uid = $this->user->getUserId();
		$with = $this->resolveCollectType($type);

		return Collect::with($with)
			->where('app_id', $appId)
			->where('uid', $uid)
			->where('type', $type)
			->order('create_time desc')
			->paginate($this->request->limit(), false, [
				'page'  => $this->request->page(),
				'query' => $this->request->get(),
			])->each(function(Collect $item) use ($appId, $type){
				if($type == Collect::CATEGORY_TYPE || $type == Collect::VISIT_CATEGORY_TYPE){
					$postCount = Post::appId($appId)->where([
						'status'      => 1,
						'category_id' => $item->topic_id,
					])->count();
					$postViewCount = Post::appId($appId)->where('category_id', $item->topic_id)->sum('view_count');
					$item['post_count'] = Num::formatSimple($postCount);
					$item['post_view_count'] = Num::formatSimple($postViewCount);
				}elseif($type == Collect::POST_TYPE){
					$imageCount = GalleryItem::appId($appId)->where('gallery_id', $item->topic_id)->count();
					$imageViewCount = GalleryItem::appId($appId)->where('gallery_id', $item->topic_id)->sum('view_count');
					$item['image_count'] = Num::formatSimple($imageCount);
					$item['image_view_count'] = Num::formatSimple($imageViewCount);
				}

				return $item;
			});
	}

	/**
	 * 是否已收藏
	 *
	 * @param int $uid
	 * @param int $type
	 * @param int $topicId
	 * @return int
	 */
	public function isCollected($type, $topicId, $uid = 0){
		$uid = $uid ? $uid : $this->user->getUserId(false);
		if(!$uid){
			return false;
		}

		return Collect::where([
			'uid'      => $uid,
			'type'     => $type,
			'topic_id' => $topicId,
		])->value('id');
	}

	/**
	 * 插入数据
	 *
	 * @param array $data
	 * @return bool
	 */
	protected function insertData(array $data){
		$model = new Collect();
		if($model->save($data) === false){
			return false;
		}

		return true;
	}

	/**
	 * 生成数据
	 *
	 * @param int $type
	 * @param int $topicId
	 * @return array
	 */
	private function resolveData($type, $topicId){
		$appId = $this->xApp->getAppId();
		$uid = $this->user->getUserId();
		return [
			'uid'         => $uid,
			'app_id'      => $appId,
			'topic_id'    => $topicId,
			'type'        => $type,
			'create_time' => $this->request->time(),
		];
	}

	/**
	 * 获取收藏类型
	 *
	 * @param string $type
	 * @return string
	 */
	private function resolveCollectType($type){
		$with = Collect::resolveTypeToWith($type);
		if(empty($with)){
			throw new ValidateException("param type invalid.");
		}

		return $with;
	}

	/**
	 * @param \Closure $closure
	 * @return mixed|null
	 */
	private function safeCallback(\Closure $closure){
		try{
			return call_user_func($closure);
		}catch(\Exception $e){
		}catch(\Throwable $e){
		}
		return null;
	}

}
